# -*- coding: utf-8 -*-

from pprint import pprint 

def topics_paths_sorted(tree = None, data=None):
    if not tree:
        tree = topics_tree(data=data, return_multiple_roots=True)

    topics_paths = flatten_branch(tree) # also sorted

    return topics_paths #dict(topics_paths = topics_paths)


def topics_tree(data=None, current_root_id=None, return_multiple_roots=None):

    if not current_root_id:
        #~ current_root_id = find_root_id()
        current_root_id = session.current_root_id or find_root_id()
        
    #~ print "\n--------------------\n"
    if data == None:
        data=db(db.Topics.id>0).select()
    #~ titles = dict([(row.id, row.title) for row in data])

    if len(data) == 0:  # if there is no data, just return empty tree
        return {}

    #~ Topics_data = dict( [(r.id, r)   for r in data] )

    tree = {}               # could be OrderedDict
    #~names = {}
    parents = {}     # stores the nesting info
    my_parent_info = {}    
    levels = {}     
    paths = {}       # seems nor very used now, excep for level count

    for row in data:
        tree[row.id] = {} #{'title': row.title, 'subtree':None}
        #~names[row.id] = row.name
        # TODO: standartize in some way: use extract_field_as_dict or prefetch_db_table_to_dict from auxiliary.py
        parents[row.id] = row.parent_id  
        my_parent_info[row.id] = {'parent_id' : row.parent_id, 'id': row.id} # to economize DB requests, when calling get_topic_path_ids
    
    #~ mylog( '== tree', tree )
    #~ mylog( '== parents', parents )
        
    for id in tree.keys():   # count nesting levels info
        paths[id] = get_topic_path_ids(id, hierarchy_info=my_parent_info) 
        levels[id] = len(paths[id])  
    
    #~ mylog( 'levels', levels )
    #~ mylog( 'paths', paths )

    # now make the tree nested
    # start looking from end, and move the nodes where they should be nested
    # the ordering of keys should not make difference

    if levels:
        for level in range(max(levels.values()), 0, -1): # should check...
            # first move deepest level data
            #~ print 'level', level
            for id in tree.keys():
                #~ print 'id', id
                if levels[id] == level:

                        #~ if not is_topic_root(my_parent_info[id]):
                        #~ if id == parents[id] or parents[id]==None: #  to prevent continuous looping, or just to leave roots as roots ;)
                            #~ continue
                            
                        #~ if not current_root_id == id: # if this is not our (chosen/current) root_id
                                                         # probably this is not necessary    
                        if True: # if this is not our (chosen/current) root_id
                            try:
                                #~ mylog()
                                tree[parents[id]].update ({id:tree.pop(id)})  # move the branch
                            except Exception, e:
                                mylog( "Error when moving the branch:", dict(level=level, id=id, parent_id=parents[id], ), msg=str(e)) # name=data[id].name

    return_multiple_roots = (request.controller=='appadmin') if return_multiple_roots==None
    if not return_multiple_roots:
        tree = { current_root_id: tree[current_root_id] } # in case we wanted just part of tree -- this gives only that part
    mylog( nested_tree=tree  )
    return tree


# AUXILIARY functions

def sort_flat_sub_branch(flat_sub_branch, parent_id,  sorting_field='order_in_topic'):

    data=db(db.Topics.parent_id == parent_id).select()
    
    #~ values4sorting = {} #  default by 'order_in_topic', could be 'name', 'id'
    #~ for row in data:
        #~ values4sorting[row.id] = row[sorting_field]
    values4sorting = extract_field_as_dict(data, sorting_field)
        
    #list_of_tuples = []
    #for sub_sub_branch in flat_sub_branch:
    #    id = sub_sub_branch[0]
    #    list_of_tuples.append(values4sorting[id], sub_sub_branch)
    #list_of_tuples.sort()
    #flat_sub_branch = [couple[1] for couple in list_of_tuples]
    def cmp_ids(id1, id2):
        result = cmp( values4sorting[id1], values4sorting[id2] )
        if not values4sorting[id1]: # if first is  empty, 
           result = -result         # reverse the result, as empty shouldn't preceed filled values
        if not values4sorting[id2]: # same for second
            result = -result 
        return result 
    def my_cmp(tpath1, tpath2):
        try:
            return cmp_ids(tpath1[0], tpath2[0])
        except Exception, e:
            mylog( 'Comparison problem', msg=str(e) )
            mylog(  tpath1, tpath2 )
            return cmp( tpath1, tpath2 )
            
    flat_sub_branch.sort(cmp=my_cmp)
    return flat_sub_branch
        
    
    
def flatten_branch(branch):
    """ flattens nested tree as topics paths """
    flat_branch = [ ]  # will become list of lists
                            # sorting would be good                        
    #~ if isinstance(branch , dict):  
    for id, sub_branch in branch.items(): 
        flat_sub_branch = flatten_branch(sub_branch) #recurse
        if flat_sub_branch:
            #~ print '\n==flat_sub_branch==', id, ':', sub_branch
            #~ pprint(flat_sub_branch)
            sort_flat_sub_branch(flat_sub_branch, parent_id = id) #sort/order
            #~ print '\nsorted:'
            #~ print(flat_sub_branch)
            for a in flat_sub_branch: # prepend self ID as parent
                a.insert(0, id)
            flat_branch.extend( [[id]]+flat_sub_branch ) # or [[id]]+ flat_sub_branch 
        else:
            flat_branch.extend( [[id]] )  # [[id]] is needed for the folder name to appear 
        
    return flat_branch
